package com.company.server;

import com.company.common.FileMetaInfo;
import com.company.common.Message;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 连接客户端的线程管理类
 */
public class ConnCliThdManage {
    private static final Map<String, ConnCliThread> THREAD_MAP = new HashMap<>();

    public static ConnCliThread get(String username) {
        return THREAD_MAP.get(username);
    }

    public static void add(String username, ConnCliThread thread) {
        THREAD_MAP.put(username, thread);
    }

    public static String[] getKeys() {
        return THREAD_MAP.keySet().toArray(new String[]{});
    }

    public static void remove(String sender) {
        THREAD_MAP.remove(sender);
    }
}

class ConnCliThread extends Thread {

    private Socket socket;

    public ConnCliThread(Socket socket) {
        this.socket = socket;
    }

    public Socket getSocket() {
        return socket;
    }

    @Override
    public void run() {
        while (!socket.isClosed()) {
            try {
                ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
                Message message = (Message) inputStream.readObject();
                switch (message.getType()) {
                    case GET_ONLINE_FRIENDS:
                        String[] users = UserDao.getOnlineUsers();
                        Message<String[]> msg = new Message<>(users, Message.MessageType.RET_ONLINE_FRIENDS, message.getSender(), "", LocalDateTime.now());
                        new ObjectOutputStream(socket.getOutputStream()).writeObject(msg);
                        break;
                    case GET_OFFLINE_MSG: // 获取离线消息/文件
                        List<Message> list = MessageDao.get(message.getSender());
                        if (list != null) {
                            list.forEach(mes -> {
                                try {
                                    new ObjectOutputStream(socket.getOutputStream()).writeObject(mes);
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            });
                            MessageDao.delete(message.getSender());
                        }
                        break;
                    case NORMAL_MSG:
                        Message<String> msgOne = new Message<>((String) message.getContent(), Message.MessageType.NORMAL_MSG, message.getReceiver(), message.getSender(), LocalDateTime.now());
                        try {
                            ConnCliThread thread = ConnCliThdManage.get(message.getReceiver());
                            if (thread == null) { // 发送离线消息
                                MessageDao.add(message);
                            } else {
                                Socket socket = thread.getSocket();
                                new ObjectOutputStream(socket.getOutputStream()).writeObject(msgOne);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        break;
                    case GROUP_MSG:
                        Message<String> msgMany = new Message<>((String) message.getContent(), Message.MessageType.GROUP_MSG, "", message.getSender(), LocalDateTime.now());
                        try {
                            for (String key : ConnCliThdManage.getKeys()) {
                                if (!key.equals(message.getSender())) {
                                    Socket socket = ConnCliThdManage.get(key).getSocket();
                                    new ObjectOutputStream(socket.getOutputStream()).writeObject(msgMany);
                                }
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        break;
                    case FILE_MSG:
                        Message<FileMetaInfo> msgFile = new Message<>((FileMetaInfo) message.getContent(), Message.MessageType.FILE_MSG, message.getReceiver(), message.getSender(), LocalDateTime.now());
                        try {
                            ConnCliThread thread = ConnCliThdManage.get(message.getReceiver());
                            if (thread == null) { // 发送离线文件
                                MessageDao.add(message);
                            } else {
                                Socket socket = thread.getSocket();
                                new ObjectOutputStream(socket.getOutputStream()).writeObject(msgFile);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        break;
                    case CLI_EXIT:
                        ConnCliThdManage.get(message.getSender()).socket.close();
                        ConnCliThdManage.remove(message.getSender());
                        System.out.println("客户端：" + message.getSender() + "退出了" + " 时间：" + LocalDateTime.now());
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
